package com.blog.cmrpersonalblog.service.impl;

import com.blog.cmrpersonalblog.dto.sensitiveword.requset.SensitiveWordCheckResult;
import com.blog.cmrpersonalblog.entity.SensitiveWord;
import com.blog.cmrpersonalblog.mapper.SensitiveWordMapper;
import com.blog.cmrpersonalblog.service.SensitiveWordService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import jakarta.annotation.PostConstruct;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 敏感词过滤服务实现类
 * 使用DFA算法实现高效的敏感词检测
 * 支持从数据库动态加载敏感词和不同过滤模式
 */
@Slf4j
@Service
public class SensitiveWordServiceImpl implements SensitiveWordService {

   @Resource
    private SensitiveWordMapper sensitiveWordMapper;

    /**
     * 敏感词库 - DFA算法的状态机
     */
    private final Map<String, Object> sensitiveWordMap = new ConcurrentHashMap<>();

    /**
     * 敏感词配置信息（从数据库加载）
     */
    private final Map<String, SensitiveWord> wordInfoMap = new ConcurrentHashMap<>();

    /**
     * 敏感词类型映射
     */
    private final Map<String, Set<String>> typeWordMap = new ConcurrentHashMap<>();

    /**
     * 初始化敏感词库
     */
    @PostConstruct
    public void init() {
        log.info("初始化敏感词库...");
        loadSensitiveWordsFromDatabase();
        log.info("敏感词库初始化完成，共加载 {} 个敏感词", wordInfoMap.size());
    }

    /**
     * 从数据库加载敏感词
     */
    private void loadSensitiveWordsFromDatabase() {
        try {
            // 清空现有数据
            sensitiveWordMap.clear();
            wordInfoMap.clear();
            typeWordMap.clear();

            // 从数据库获取所有启用的敏感词
            List<SensitiveWord> sensitiveWords = sensitiveWordMapper.selectAllEnabled();

            for (SensitiveWord sensitiveWord : sensitiveWords) {
                String word = sensitiveWord.getWord().trim().toLowerCase();

                // 添加到DFA状态机
                addWordToMap(word);

                // 保存词汇信息
                wordInfoMap.put(word, sensitiveWord);

                // 按类型分组
                typeWordMap.computeIfAbsent(sensitiveWord.getType(), k -> new HashSet<>()).add(word);

                log.debug("加载敏感词: {} (类型: {}, 严重程度: {}, 过滤模式: {})",
                         word, sensitiveWord.getType(), sensitiveWord.getSeverity(), sensitiveWord.getFilterMode());
            }

            log.info("从数据库加载敏感词完成，共 {} 个", sensitiveWords.size());
        } catch (Exception e) {
            log.error("从数据库加载敏感词失败，使用默认敏感词库", e);
            initDefaultSensitiveWords();
        }
    }

    /**
     * 初始化默认敏感词库（作为备用）
     */
    private void initDefaultSensitiveWords() {
        // 脏话类
        List<String> profanityWords = Arrays.asList(
            "傻逼", "草泥马", "去死", "滚蛋", "白痴", "智障", "废物", "垃圾",
            "操你", "妈的", "狗屎", "混蛋", "王八蛋", "贱人", "婊子"
        );
        addSensitiveWords(profanityWords, "profanity", 4);

        // 政治敏感词
        List<String> politicsWords = Arrays.asList(
            "法轮功", "六四", "天安门", "达赖", "台独", "藏独", "疆独",
            "反政府", "颠覆国家", "煽动分裂"
        );
        addSensitiveWords(politicsWords, "politics", 5);

        // 广告词
        List<String> adWords = Arrays.asList(
            "代开发票", "办证", "刻章", "贷款", "股票推荐", "彩票",
            "博彩", "赌博", "色情", "成人用品", "微信号", "QQ群"
        );
        addSensitiveWords(adWords, "advertisement", 3);

        // 暴力词汇
        List<String> violenceWords = Arrays.asList(
            "杀死", "自杀", "爆炸", "恐怖袭击", "血腥", "暴力",
            "砍死", "毒死", "勒死", "枪杀"
        );
        addSensitiveWords(violenceWords, "violence", 4);

        // 违法内容
        List<String> illegalWords = Arrays.asList(
            "毒品", "海洛因", "冰毒", "摇头丸", "大麻", "制毒",
            "贩毒", "洗钱", "诈骗", "传销", "非法集资"
        );
        addSensitiveWords(illegalWords, "illegal", 5);
    }

    @Override
    public SensitiveWordCheckResult checkSensitiveWords(String content) {
        if (content == null || content.trim().isEmpty()) {
            return new SensitiveWordCheckResult(content);
        }

        SensitiveWordCheckResult result = new SensitiveWordCheckResult(content);
        StringBuilder filteredContent = new StringBuilder(content);

        // 记录已替换的位置，避免重复替换
        List<int[]> replacedRanges = new ArrayList<>();
        List<String> blockedWords = new ArrayList<>(); // 记录需要拦截的敏感词

        // 使用DFA算法检测敏感词
        char[] chars = content.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            int length = checkSensitiveWord(chars, i);
            if (length > 0) {
                String sensitiveWordText = content.substring(i, i + length);
                SensitiveWord wordInfo = wordInfoMap.get(sensitiveWordText.toLowerCase());

                if (wordInfo != null) {
                    result.addSensitiveWord(sensitiveWordText, wordInfo.getType(), wordInfo.getSeverity(), i);

                    // 更新敏感词匹配统计
                    updateMatchCount(sensitiveWordText);

                    // 根据过滤模式处理
                    if ("BLOCK".equals(wordInfo.getFilterMode())) {
                        // BLOCK模式：记录拦截词汇
                        blockedWords.add(sensitiveWordText);
                    } else {
                        // REPLACE模式：记录需要替换的范围
                        replacedRanges.add(new int[]{i, i + length, wordInfo.getId().intValue()});
                    }
                }

                i += length - 1; // 跳过已检测的字符
            }
        }

        // 如果有BLOCK模式的敏感词，设置建议操作为拦截
        if (!blockedWords.isEmpty()) {
            result.setSuggestedAction("BLOCK");
            result.getDetails().put("blockedWords", blockedWords);
        }

        // 从后往前替换，避免位置偏移问题
        replacedRanges.sort((a, b) -> Integer.compare(b[0], a[0]));
        for (int[] range : replacedRanges) {
            int start = range[0];
            int end = range[1];
            int wordId = range[2];

            // 获取自定义替换文本
            String replacement = getReplacementText(wordId, end - start);
            filteredContent.replace(start, end, replacement);
        }

        result.setFilteredContent(filteredContent.toString());
        return result;
    }

    /**
     * 获取替换文本
     */
    private String getReplacementText(int wordId, int originalLength) {
        try {
            SensitiveWord sensitiveWord = sensitiveWordMapper.selectById((long) wordId);
            if (sensitiveWord != null && sensitiveWord.getReplacement() != null && !sensitiveWord.getReplacement().trim().isEmpty()) {
                return sensitiveWord.getReplacement();
            }
        } catch (Exception e) {
            log.warn("获取自定义替换文本失败，使用默认替换", e);
        }

        // 默认使用*替换
        return "*".repeat(originalLength);
    }

    /**
     * 更新敏感词匹配统计
     */
    private void updateMatchCount(String word) {
        try {
            sensitiveWordMapper.updateMatchCount(word.toLowerCase());
        } catch (Exception e) {
            log.warn("更新敏感词匹配统计失败: {}", word, e);
        }
    }

    @Override
    public String filterSensitiveWords(String content) {
        SensitiveWordCheckResult result = checkSensitiveWords(content);
        return result.getFilteredContent();
    }

    @Override
    public boolean containsSensitiveWords(String content) {
        SensitiveWordCheckResult result = checkSensitiveWords(content);
        return result.isHasSensitiveWords();
    }

    @Override
    public List<String> findSensitiveWords(String content) {
        SensitiveWordCheckResult result = checkSensitiveWords(content);
        if (result.getSensitiveWords() == null) {
            return new ArrayList<>();
        }
        
        return result.getSensitiveWords().stream()
                .map(SensitiveWordCheckResult.SensitiveWord::getWord)
                .distinct()
                .collect(java.util.stream.Collectors.toList());
    }

    @Override
    public void addSensitiveWord(String word, String type, int severity) {
        if (word == null || word.trim().isEmpty()) {
            return;
        }

        word = word.trim().toLowerCase();

        // 添加到DFA状态机
        addWordToMap(word);

        // 创建临时敏感词对象（用于兼容旧接口）
        SensitiveWord sensitiveWord = new SensitiveWord();
        sensitiveWord.setWord(word);
        sensitiveWord.setType(type);
        sensitiveWord.setSeverity(severity);
        sensitiveWord.setFilterMode("REPLACE"); // 默认替换模式
        sensitiveWord.setStatus(1); // 默认启用

        // 保存词汇信息
        wordInfoMap.put(word, sensitiveWord);

        // 按类型分组
        typeWordMap.computeIfAbsent(type, k -> new HashSet<>()).add(word);

        log.debug("添加敏感词: {} (类型: {}, 严重程度: {})", word, type, severity);
    }

    @Override
    public void removeSensitiveWord(String word) {
        if (word == null || word.trim().isEmpty()) {
            return;
        }

        word = word.trim().toLowerCase();

        // 从状态机中移除（这里简化处理，实际应该重建状态机）
        SensitiveWord wordInfo = wordInfoMap.remove(word);
        if (wordInfo != null) {
            Set<String> typeWords = typeWordMap.get(wordInfo.getType());
            if (typeWords != null) {
                typeWords.remove(word);
                if (typeWords.isEmpty()) {
                    typeWordMap.remove(wordInfo.getType());
                }
            }
        }

        log.debug("删除敏感词: {}", word);
    }

    @Override
    public void addSensitiveWords(List<String> words, String type, int severity) {
        if (words == null || words.isEmpty()) {
            return;
        }
        
        for (String word : words) {
            addSensitiveWord(word, type, severity);
        }
    }

    @Override
    public Set<String> getAllSensitiveWords() {
        return new HashSet<>(wordInfoMap.keySet());
    }

    @Override
    public Set<String> getSensitiveWordsByType(String type) {
        return typeWordMap.getOrDefault(type, new HashSet<>());
    }

    @Override
    public void refreshSensitiveWords() {
        log.info("刷新敏感词库...");
        loadSensitiveWordsFromDatabase();
        log.info("敏感词库刷新完成");
    }

    @Override
    public Map<String, Object> getSensitiveWordStatistics() {
        Map<String, Object> stats = new HashMap<>();
        stats.put("totalWords", wordInfoMap.size());

        Map<String, Integer> typeStats = new HashMap<>();
        for (Map.Entry<String, Set<String>> entry : typeWordMap.entrySet()) {
            typeStats.put(entry.getKey(), entry.getValue().size());
        }
        stats.put("typeDistribution", typeStats);

        return stats;
    }

    @Override
    public boolean validateSensitiveWordConfig() {
        return !sensitiveWordMap.isEmpty() && !wordInfoMap.isEmpty();
    }

    @Override
    public String exportSensitiveWords() {
        StringBuilder sb = new StringBuilder();
        for (SensitiveWord info : wordInfoMap.values()) {
            sb.append(info.getWord()).append(",")
              .append(info.getType()).append(",")
              .append(info.getSeverity()).append(",")
              .append(info.getFilterMode()).append("\n");
        }
        return sb.toString();
    }

    @Override
    public boolean importSensitiveWords(String data) {
        try {
            String[] lines = data.split("\n");
            for (String line : lines) {
                String[] parts = line.split(",");
                if (parts.length >= 3) {
                    String word = parts[0].trim();
                    String type = parts[1].trim();
                    int severity = Integer.parseInt(parts[2].trim());
                    addSensitiveWord(word, type, severity);
                }
            }
            return true;
        } catch (Exception e) {
            log.error("导入敏感词失败", e);
            return false;
        }
    }

    /**
     * 将敏感词添加到DFA状态机
     */
    @SuppressWarnings("unchecked")
    private void addWordToMap(String word) {
        Map<String, Object> currentMap = sensitiveWordMap;
        char[] chars = word.toCharArray();
        
        for (int i = 0; i < chars.length; i++) {
            String key = String.valueOf(chars[i]);
            Map<String, Object> nextMap = (Map<String, Object>) currentMap.get(key);
            
            if (nextMap == null) {
                nextMap = new HashMap<>();
                currentMap.put(key, nextMap);
            }
            
            currentMap = nextMap;
            
            // 最后一个字符，标记为结束
            if (i == chars.length - 1) {
                currentMap.put("isEnd", true);
            }
        }
    }

    /**
     * 检测敏感词长度
     */
    @SuppressWarnings("unchecked")
    private int checkSensitiveWord(char[] chars, int startIndex) {
        Map<String, Object> currentMap = sensitiveWordMap;
        int length = 0;
        boolean isEnd = false;
        
        for (int i = startIndex; i < chars.length; i++) {
            String key = String.valueOf(chars[i]);
            currentMap = (Map<String, Object>) currentMap.get(key);
            
            if (currentMap == null) {
                break;
            }
            
            length++;
            
            if (currentMap.containsKey("isEnd")) {
                isEnd = true;
            }
        }
        
        return isEnd ? length : 0;
    }

}
